#pragma once
#include "Socket.hpp"
#include <string>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <sys/types.h>
#include <fstream>
#include <sstream>
#include <sys/socket.h>

const std::string webcontent="./wwwroot";//web根目录
const std::string homehtml="index.html";//默认首页
const std::string sep="\r\n";//http报文的分隔符

LOG log(PRINT_TO_SCREEN);

class HttpServer;
struct ThreadData
{
    ThreadData(int s, HttpServer* hs)
        : sockfd(s)
        , httpserver(hs)
    {
    }
    int sockfd;
    HttpServer* httpserver;
};

class HttpRequest
{
public:
    HttpRequest()
    {
        // 初始化HTTP请求
    }

    void Deserialize(std::string& request)
    {
        while(1)
        {
            size_t pos=request.find(sep);
            if(pos==std::string::npos) break;
            std::string line=request.substr(0,pos);
            req_headers.push_back(line);
            request.erase(0,pos+sep.size());
        }
        text=request;//剩下的都是有效载荷
    }

    void Parse()
    {
        stringstream ss(req_headers[0]);
        ss >> method >> url >> version;
        std::string file_name(webcontent);
        if(url=="/"||url=="index.html") file_name+=("/"+homehtml);//默认首页
        else file_name+=url;
        file_path=file_name;
    }


    void DebugPrint()
    {
        for(auto &line : req_headers)
        {
            std::cout << "--------------------------------" << std::endl;
            std::cout << line << "\n\n";
        }

        std::cout << "method: " << method << std::endl;
        std::cout << "url: " << url << std::endl;
        std::cout << "http_version: " << version << std::endl;
        std::cout << "file_path: " << file_path << std::endl;
        std::cout << text << std::endl;
    }

    std::string GetFilePath()
    {
        return file_path;
    }
    ~HttpRequest()
    {
        // 清理HTTP请求
    }
private:
    std::vector<std::string> req_headers; 
    std::string method; // 请求方法
    std::string url; // 请求的URL
    std::string version; // HTTP版本

    std::string text;//正文部分
    std::string file_path; // 文件路径
};

class HttpServer
{
public:
    HttpServer(uint16_t port=8080)
        : port_(port)
    {
    }

    void Init()
    {
        listensocket_.Socket(); // 创建套接字
        listensocket_.Bind(port_); // 绑定端口
        listensocket_.Listen(); // 开始监听
    }

    std::string ReadHtmlContent(const std::string &file_path)
    {
        std::ifstream file(file_path);
        if (!file.is_open())
        {
            return "<html><body><h1>404 Not Found</h1></body></html>";
        }
        std::string tmp,ret;
        while(getline(file,tmp))
        {
            ret += tmp;
        }
        return ret;
    }

    void HandlerHttp(int sockfd)
    {
        char buf[40960]={0};
        ssize_t n=recv(sockfd, buf, sizeof(buf)-1, 0);//recv与read相同
        if(n > 0)
        {
            buf[n] = '\0';
            // 解析HTTP请求
            std::string request(buf);
            HttpRequest req;
            req.Deserialize(request); // Deserialize方法来解析HTTP请求
            req.Parse(); 

            req.DebugPrint();

            // 处理请求并生成响应
            std::string file_path = req.GetFilePath();
            std::string test=ReadHtmlContent(file_path);
            std::string response_header="HTTP/1.1 200 OK\r\n";
            std::string response_mid="Content-Length: "+std::to_string(test.size())+"\r\n";
            std::string response_space="\r\n";
            std::string response=response_header+response_mid+response_space+test;
            send(sockfd, response.c_str(), response.size(), 0);//send与write相同
        }
        else
        {
            log(WARNING, "recv error or client closed, n: %ld", n);
        }
        close(sockfd);
    }

    static void* threadfunc(void* arg)
    {
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(arg);
        td->httpserver->HandlerHttp(td->sockfd);
        delete td; 
        return nullptr;
    }
    void Run()
    {
        while (true)
        {
            int client_socket = 0;
            std::string client_ip;
            uint16_t client_port;
            if (!listensocket_.Accept(client_socket, client_ip, client_port))
            {
                log(FATAL, "accept error");
                continue; // 如果接受连接失败，继续等待下一个连接
            }
            else 
            {
                log(INFO, "accept success, client_ip: %s, client_port: %d", client_ip.c_str(), client_port);
            }

            pthread_t tid;
            ThreadData* td = new ThreadData(client_socket, this);
            pthread_create(&tid, nullptr, threadfunc, (void*)td);
        }
    }

    ~HttpServer()
    {
        listensocket_.Close(); 
    }
private:
    uint16_t port_;
    Sockets listensocket_;
};